#include "stdafx.h"
#include <memory>
#include "DeviceEnumerator.h"
#include "FakeDirect3D9.h"
#include "FakeDeviceEnumerationFilter.h"

std::ostream &operator<<(std::ostream &stream, D3DCAPS9 const &caps)
{
	return stream << "D3DCAPS9";
}

bool operator==(D3DPSHADERCAPS2_0 const &left, D3DPSHADERCAPS2_0 const &right)
{
	return (left.Caps == right.Caps)
		&& (left.DynamicFlowControlDepth == right.DynamicFlowControlDepth)
		&& (left.NumTemps == right.NumTemps)
		&& (left.StaticFlowControlDepth == right.StaticFlowControlDepth)
		&& (left.NumInstructionSlots == right.NumInstructionSlots);
}

bool operator==(D3DVSHADERCAPS2_0 const &left, D3DVSHADERCAPS2_0 const &right)
{
	return (left.Caps == right.Caps)
		&& (left.DynamicFlowControlDepth == right.DynamicFlowControlDepth)
		&& (left.NumTemps == right.NumTemps)
		&& (left.StaticFlowControlDepth == right.StaticFlowControlDepth);
}

bool operator==(D3DCAPS9 const &left, D3DCAPS9 const &right)
{
	return (left.AdapterOrdinal == right.AdapterOrdinal)
		&& (left.AdapterOrdinalInGroup == right.AdapterOrdinalInGroup)
		&& (left.AlphaCmpCaps == right.AlphaCmpCaps)
		&& (left.Caps == right.Caps)
		&& (left.Caps2 == right.Caps2)
		&& (left.Caps3 == right.Caps3)
		&& (left.CubeTextureFilterCaps == right.CubeTextureFilterCaps)
		&& (left.CursorCaps == right.CursorCaps)
		&& (left.DeclTypes == right.DeclTypes)
		&& (left.DestBlendCaps == right.DestBlendCaps)
		&& (left.DevCaps == right.DevCaps)
		&& (left.DevCaps2 == right.DevCaps2)
		&& (left.DeviceType == right.DeviceType)
		&& (left.ExtentsAdjust == right.ExtentsAdjust)
		&& (left.FVFCaps == right.FVFCaps)
		&& (left.GuardBandBottom == right.GuardBandBottom)
		&& (left.GuardBandLeft == right.GuardBandLeft)
		&& (left.GuardBandRight == right.GuardBandRight)
		&& (left.GuardBandTop == right.GuardBandTop)
		&& (left.LineCaps == right.LineCaps)
		&& (left.MasterAdapterOrdinal == right.MasterAdapterOrdinal)
		&& (left.MaxActiveLights == right.MaxActiveLights)
		&& (left.MaxAnisotropy == right.MaxAnisotropy)
		&& (left.MaxNpatchTessellationLevel == right.MaxNpatchTessellationLevel)
		&& (left.MaxPixelShader30InstructionSlots == right.MaxPixelShader30InstructionSlots)
		&& (left.MaxPointSize == right.MaxPointSize)
		&& (left.MaxPrimitiveCount == right.MaxPrimitiveCount)
		&& (left.MaxPShaderInstructionsExecuted == right.MaxPShaderInstructionsExecuted)
		&& (left.MaxSimultaneousTextures == right.MaxSimultaneousTextures)
		&& (left.MaxStreams == right.MaxStreams)
		&& (left.MaxStreamStride == right.MaxStreamStride)
		&& (left.MaxTextureAspectRatio == right.MaxTextureAspectRatio)
		&& (left.MaxTextureBlendStages == right.MaxTextureBlendStages)
		&& (left.MaxTextureHeight == right.MaxTextureHeight)
		&& (left.MaxTextureRepeat == right.MaxTextureRepeat)
		&& (left.MaxTextureWidth == right.MaxTextureWidth)
		&& (left.MaxUserClipPlanes == right.MaxUserClipPlanes)
		&& (left.MaxVertexBlendMatrices == right.MaxVertexBlendMatrices)
		&& (left.MaxVertexBlendMatrixIndex == right.MaxVertexBlendMatrixIndex)
		&& (left.MaxVertexIndex == right.MaxVertexIndex)
		&& (left.MaxVertexShader30InstructionSlots == right.MaxVertexShader30InstructionSlots)
		&& (left.MaxVertexShaderConst == right.MaxVertexShaderConst)
		&& (left.MaxVertexW == right.MaxVertexW)
		&& (left.MaxVolumeExtent == right.MaxVolumeExtent)
		&& (left.MaxVShaderInstructionsExecuted == right.MaxVShaderInstructionsExecuted)
		&& (left.NumberOfAdaptersInGroup == right.NumberOfAdaptersInGroup)
		&& (left.NumSimultaneousRTs == right.NumSimultaneousRTs)
		&& (left.PixelShader1xMaxValue == right.PixelShader1xMaxValue)
		&& (left.PixelShaderVersion == right.PixelShaderVersion)
		&& (left.PresentationIntervals == right.PresentationIntervals)
		&& (left.PrimitiveMiscCaps == right.PrimitiveMiscCaps)
		&& (left.PS20Caps == right.PS20Caps)
		&& (left.RasterCaps == right.RasterCaps)
		&& (left.ShadeCaps == right.ShadeCaps)
		&& (left.SrcBlendCaps == right.SrcBlendCaps)
		&& (left.StencilCaps == right.StencilCaps)
		&& (left.StretchRectFilterCaps == right.StretchRectFilterCaps)
		&& (left.TextureAddressCaps == right.TextureAddressCaps)
		&& (left.TextureCaps == right.TextureCaps)
		&& (left.TextureFilterCaps == right.TextureFilterCaps)
		&& (left.TextureOpCaps == right.TextureOpCaps)
		&& (left.VertexProcessingCaps == right.VertexProcessingCaps)
		&& (left.VertexShaderVersion == right.VertexShaderVersion)
		&& (left.VertexTextureFilterCaps == right.VertexTextureFilterCaps)
		&& (left.VolumeTextureAddressCaps == right.VolumeTextureAddressCaps)
		&& (left.VolumeTextureFilterCaps == right.VolumeTextureFilterCaps)
		&& (left.VS20Caps == right.VS20Caps)
		&& (left.ZCmpCaps == right.ZCmpCaps);
}

BOOST_AUTO_TEST_CASE(DeviceEnumerator_Construct)
{
	rt::Fakes::FakeDirect3D9 d3d;
	std::auto_ptr<rt::IDeviceEnumerator> enumerator(rtCreateDeviceEnumerator(&d3d));
	BOOST_REQUIRE(enumerator.get());
}

BOOST_AUTO_TEST_CASE(DeviceEnumerator_EnumerateSingleAdapter)
{
	rt::Fakes::FakeDirect3D9 d3d;
	d3d.GetAdapterCountFakeResult = 1;
	d3d.GetDeviceCapsFakeHResult.push_back(S_OK);
	d3d.GetAdapterModeCountFakeResult.push_back(1U);
	rt::Fakes::FakeDirect3D9::EnumAdapterModesFakeResultKey key = { 0, D3DFMT_X8R8G8B8, 0 };
	D3DDISPLAYMODE mode = { 640, 480, 60, D3DFMT_X8R8G8B8 };
	d3d.EnumAdapterModesFakeResult[key] = mode;
	d3d.EnumAdapterModesFakeHResult[key] = S_OK;
	D3DCAPS9 caps = { D3DDEVTYPE_HAL };
	caps.AdapterOrdinal = 0;
	d3d.GetDeviceCapsFakeResult.push_back(caps);
	std::auto_ptr<rt::IDeviceEnumerator> enumerator(rtCreateDeviceEnumerator(&d3d));
	FakeDeviceEnumerationFilter filter;
	enumerator->Enumerate(&filter);
	BOOST_REQUIRE(d3d.GetAdapterCountCalled);
	BOOST_REQUIRE(d3d.EnumAdapterModesCalled);
	BOOST_REQUIRE(d3d.GetDeviceCapsCalled);
	BOOST_REQUIRE(filter.IsDeviceAcceptableCalled);
	BOOST_REQUIRE_EQUAL(caps, filter.IsDeviceAcceptableLastCaps);
	BOOST_REQUIRE_EQUAL(D3DFMT_X8R8G8B8, filter.IsDeviceAcceptableLastAdapterFormat);
	BOOST_REQUIRE_EQUAL(D3DFMT_X8R8G8B8, filter.IsDeviceAcceptableLastBackBufferFormat);
}
